﻿#if IMPLEMENT_NOTIFY_ICON
namespace Standard
{
    using System;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows;
    using System.Windows.Interop;

    internal class NotifyIcon : Freezable
    {
        private HwndSource _hwnd;
        /// <summary>
        /// Message received when the taskbar has been created.
        /// </summary>
        /// <remarks>
        /// Trying to call Shell_NotifyIcon too early may fail, and we also want to ensure that the icon
        /// appears in cases where Explorer restarts.
        /// </remarks>
        private static readonly WM WM_TASKBARCREATED = NativeMethods.RegisterWindowMessage("TaskbarCreated");

        protected override Freezable CreateInstanceCore()
        {
            return new NotifyIcon();
        }

        public NotifyIcon()
        {
            var hwndParams = new HwndSourceParameters
            {
                HwndSourceHook = _WndProc,
                WindowName = "WPF_NotifyIcon",
            };
            _hwnd = new HwndSource(hwndParams);
        }

        private IntPtr _WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            return IntPtr.Zero;
        }

        #region Attached Properties

        /// <summary>
        /// NotifyIcon Attached Dependency Property
        /// </summary>
        public static readonly DependencyProperty NotifyIconProperty = DependencyProperty.RegisterAttached(
            "NotifyIcon",
            typeof(NotifyIcon),
            typeof(NotifyIcon),
            new PropertyMetadata(
                null,
                OnNotifyIconChanged));

        /// <summary>
        /// Gets the NotifyIcon property.  This dependency property 
        /// indicates ....
        /// </summary>
        public static NotifyIcon GetNotifyIcon(Window window)
        {
            Verify.IsNotNull(window, "window");
            return (NotifyIcon)window.GetValue(NotifyIconProperty);
        }

        /// <summary>
        /// Sets the NotifyIcon property.  This dependency property 
        /// indicates ....
        /// </summary>
        public static void SetNotifyIcon(Window window, NotifyIcon value)
        {
            Verify.IsNotNull(window, "window");
            window.SetValue(NotifyIconProperty, value);
        }

        /// <summary>
        /// Handles changes to the NotifyIcon property.
        /// </summary>
        private static void OnNotifyIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        #endregion

        #region Dependency Properties

        /// <summary>
        /// BalloonTipIcon Dependency Property
        /// </summary>
        public static readonly DependencyProperty BalloonTipIconProperty = DependencyProperty.Register(
            "BalloonTipIcon",
            typeof(ImageSource), 
            typeof(NotifyIcon),
            new PropertyMetadata(
                null,
                (d, e) => ((NotifyIcon)d)._OnBalloonTipIconChanged(e)));

        /// <summary>
        /// Gets or sets the BalloonTipIcon property.  This dependency property 
        /// indicates the balloon tip icon.
        /// </summary>
        public ImageSource BalloonTipIcon
        {
            get { return (ImageSource)GetValue(BalloonTipIconProperty); }
            set { SetValue(BalloonTipIconProperty, value); }
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the BalloonTipIcon property.
        /// </summary>
        private void _OnBalloonTipIconChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #region BalloonTipText

        /// <summary>
        /// BalloonTipText Dependency Property
        /// </summary>
        public static readonly DependencyProperty BalloonTipTextProperty =
            DependencyProperty.Register("BalloonTipText", typeof(string), typeof(NotifyIcon),
                new PropertyMetadata((string)null, 
                    new PropertyChangedCallback(OnBalloonTipTextChanged), 
                    new CoerceValueCallback(CoerceBalloonTipTextValue)));

        /// <summary>
        /// Gets or sets the BalloonTipText property.  This dependency property 
        /// indicates the balloon tip text.
        /// </summary>
        public string BalloonTipText
        {
            get { return (string)GetValue(BalloonTipTextProperty); }
            set { SetValue(BalloonTipTextProperty, value); }
        }

        /// <summary>
        /// Handles changes to the BalloonTipText property.
        /// </summary>
        private static void OnBalloonTipTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((NotifyIcon)d).OnBalloonTipTextChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the BalloonTipText property.
        /// </summary>
        protected virtual void OnBalloonTipTextChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        /// <summary>
        /// Coerces the BalloonTipText value.
        /// </summary>
        private static object CoerceBalloonTipTextValue(DependencyObject d, object value)
        {
            return value;
        }
        
        #endregion

        #region BalloonTipTitle

        /// <summary>
        /// BalloonTipTitle Dependency Property
        /// </summary>
        public static readonly DependencyProperty BalloonTipTitleProperty =
            DependencyProperty.Register("BalloonTipTitle", typeof(string), typeof(NotifyIcon),
                new PropertyMetadata((string)null, 
                    new PropertyChangedCallback(OnBalloonTipTitleChanged), 
                    new CoerceValueCallback(CoerceBalloonTipTitleValue)));

        /// <summary>
        /// Gets or sets the BalloonTipTitle property.  This dependency property 
        /// indicates balloon tip title.
        /// </summary>
        public string BalloonTipTitle
        {
            get { return (string)GetValue(BalloonTipTitleProperty); }
            set { SetValue(BalloonTipTitleProperty, value); }
        }

        /// <summary>
        /// Handles changes to the BalloonTipTitle property.
        /// </summary>
        private static void OnBalloonTipTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((NotifyIcon)d).OnBalloonTipTitleChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the BalloonTipTitle property.
        /// </summary>
        protected virtual void OnBalloonTipTitleChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        /// <summary>
        /// Coerces the BalloonTipTitle value.
        /// </summary>
        private static object CoerceBalloonTipTitleValue(DependencyObject d, object value)
        {
            return value;
        }
        
        #endregion

        #region Source

        /// <summary>
        /// Source Dependency Property
        /// </summary>
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(ImageSource), typeof(NotifyIcon),
                new PropertyMetadata((ImageSource)null, 
                    new PropertyChangedCallback(OnSourceChanged)));

        /// <summary>
        /// Gets or sets the Source property.  This dependency property 
        /// indicates the image to display in the tray.
        /// </summary>
        public ImageSource Source
        {
            get { return (ImageSource)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        /// <summary>
        /// Handles changes to the Source property.
        /// </summary>
        private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((NotifyIcon)d).OnSourceChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the Source property.
        /// </summary>
        protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion

        #region UseLargeIcon

        /// <summary>
        /// UseLargeIcon Dependency Property
        /// </summary>
        public static readonly DependencyProperty UseLargeIconProperty =
            DependencyProperty.Register("UseLargeIcon", typeof(bool), typeof(NotifyIcon),
                new PropertyMetadata((bool)false, 
                    new PropertyChangedCallback(OnUseLargeIconChanged)));

        /// <summary>
        /// Gets or sets the UseLargeIcon property.  This dependency property 
        /// indicates whether to use a large icon when displaying balloon notifications.
        /// </summary>
        public bool UseLargeIcon
        {
            get { return (bool)GetValue(UseLargeIconProperty); }
            set { SetValue(UseLargeIconProperty, value); }
        }

        /// <summary>
        /// Handles changes to the UseLargeIcon property.
        /// </summary>
        private static void OnUseLargeIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((NotifyIcon)d).OnUseLargeIconChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the UseLargeIcon property.
        /// </summary>
        protected virtual void OnUseLargeIconChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion

        #region Description

        /// <summary>
        /// Description Dependency Property
        /// </summary>
        public static readonly DependencyProperty DescriptionProperty =
            DependencyProperty.Register("Description", typeof(string), typeof(NotifyIcon),
                new PropertyMetadata((string)null, 
                    new PropertyChangedCallback(OnDescriptionChanged), 
                    new CoerceValueCallback(CoerceDescriptionValue)));

        /// <summary>
        /// Gets or sets the Description property.  This dependency property 
        /// indicates the description of this icon.
        /// </summary>
        public string Description
        {
            get { return (string)GetValue(DescriptionProperty); }
            set { SetValue(DescriptionProperty, value); }
        }

        /// <summary>
        /// Handles changes to the Description property.
        /// </summary>
        private static void OnDescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((NotifyIcon)d).OnDescriptionChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the Description property.
        /// </summary>
        protected virtual void OnDescriptionChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        /// <summary>
        /// Coerces the Description value.
        /// </summary>
        private static object CoerceDescriptionValue(DependencyObject d, object value)
        {
            return value;
        }
        
        #endregion


        #endregion

        public ImageSource BalloonTipIcon { get; set; }
        public string BalloonTipText { get; set; }
        public string BalloonTipTitle { get; set; }
        public ContextMenu ContextMenu { get; set; }
        public ImageSource Icon { get; set; }
        public bool LargeIcon { get; set; }
        public string Description { get; set; }
        public bool Visible { get; set; }
        public int TooltipDuration { get; set; }

        public void ShowBalloonTip() { }

        public event EventHandler BalloonTipClicked;
        public event EventHandler BalloonTipClosed;
        public event EventHandler BalloonTipShown;
        public event EventHandler Click;
        public event EventHandler MouseClick;
        public event EventHandler MouseDoubleClick;
        public event EventHandler MouseDown;
        public event EventHandler MouseMove;
        public event EventHandler MouseUp;

    }
}
#endif